//红外遥控库
#include <ESP8266WiFi.h>//ESP8266WiFi设置库
#include <IRremoteESP8266.h>//ESP8266红外控制库
#include <IRsend.h>//红外发送库
#include <ir_Electra.h>//添加奥克斯空调的库

//Wifi连接库
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include <NTPClient_Generic.h>


//DHT11温度传感器库
#include <SimpleDHT.h>
#include <DHT.h>
#include <DHT_U.h>

//OLED显示屏库
#include <U8g2lib.h>


//Tcp和Udp库
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>

//Json解析库
#include <ArduinoJson.h>

//按键库
#include <Bounce2.h>

#include <PubSubClient.h>

//定时器库
#include <Ticker.h> 

//太空人启动动画
#include "spaceman.h"



//定义绘制信息提示页面的类型标识
#define ERR 0
#define WARN 1
#define INFO 2
#define TEXT 3

//OLED引脚定义
#define SCL 4
#define SDA 5
//OLED iic驱动
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);

//按键引脚定义
int BUTTON_PIN = 0;
Bounce2::Button button = Bounce2::Button();//实例化一个抖动对象

//DHT11温湿度定义
//int pinDHT11 = 12;
int temperature = 0;
int humidity = 0;
//SimpleDHT11 dht11(pinDHT11);
#define DHTPIN 12
#define DHTTYPE    DHT11
DHT dht(DHTPIN, DHTTYPE);


//气体传感器引脚定义
#define Sensor_AO A0
unsigned int sensorValue = 0;

//继电器引脚定义
int pinJD = 16;

//遥控定义
IRElectraAc  _ac(14); //创建一个奥克斯空调的控制实例

//配网定义
const char* AP_NAME = "Esp8266配网";//wifi名字
const byte DNS_PORT = 53;//DNS端口号
IPAddress apIP(192, 168, 4, 1);//esp8266-AP-IP地址
DNSServer dnsServer;//创建dnsServer实例
ESP8266WebServer server(80);//创建WebServer
//wifi账号密码存储
char my_auth[32] = {0};
char my_ssid[32] = {0};
char my_password[64] = {0};

int IMG_PAGE=0;//太空人动画页
uint8_t PAGE = 0;//主系统页

//这里定义了横幅的初始文字，避免因为获取失败造成无法显示
char MSG[127]="给时光以生命,给岁月以文明";
int16_t OFFSET = -(int16_t)u8g2.getDisplayWidth();

//时间定义
int HOURS = 8;
int MINS = 0;
int SECS = 0;

unsigned long T = 0;

uint32_t TPF = 30;//Time Per Frames
//城市定义
char city[16] = "Zhengzhou";//城市
char city_CH[16] = "郑州";


//服务器数据交互定义
char TIME_SERVER[] = "ntp1.aliyun.com";
char IOTAPI_URL[] = "api.bemfa.com";
char IPSTACKAPI_URL[] = "api.bemfa.com";

String IPS = "Location";//定位城市消息主题

String LIGHTSWIC="LightSwitch002";//控制灯主题
String AIRSWIC = "AIRSWITCH005";//控制空调主题
String USR = "Msg";//滚动消息主题
// 建立发布主题
//巴法云个性设置，推送消息时：主题名后加/set推送消息，表示向所有订阅这个主题的设备们推送消息，
//假如推送者自己也订阅了这个主题，消息不会被推送给它自己，以防止自己推送的消息被自己接收。
String dht11TopicString = "TEMPSENSOR004/set" ;

//巴法云服务器地址端口定义
//Tcp连接定义
#define TCP_SERVER_ADDR "bemfa.com"
#define TCP_SERVER_PORT "8344"
String UID = "88e2081da9c5a74deb018e9206621cba";
//Mqtt连接定义
const char* mqtt_server = "bemfa.com";


bool C_F = 1;

unsigned long TIME = 0;
unsigned long LAST_TIME = 0;


//ntp time part
#define TIME_ZONE_OFFSET_HRS            (8)
#define NTP_UPDATE_INTERVAL_MS          60000L
WiFiUDP NTP_UDP;
NTPClient TIME_CLIENT(NTP_UDP, TIME_SERVER, (3600 * TIME_ZONE_OFFSET_HRS), NTP_UPDATE_INTERVAL_MS);

//TCP初始化连接
void doTCPClientTick();
void startTCPClient();
void sendtoTCPServer(String p);

//**************************************************//
//最大字节数
#define MAX_PACKETSIZE 512
//设置心跳值60s
#define KEEPALIVEATIME 60*1000
//tcp客户端相关初始化，默认即可
WiFiClient TCPclient;
PubSubClient client(TCPclient);

String TcpClient_Buff = "";//初始化字符串，用于接收服务器发来的数据
unsigned int TcpClient_BuffIndex = 0;
unsigned long TcpClient_preTick = 0;
unsigned long preHeartTick = 0;//心跳
unsigned long preTCPStartTick = 0;//连接
bool preTCPConnected = false;

Ticker ticker;  //定时器对象
int tickercount;    // Ticker计数用的变量


//配网页面代码
String HTML_TITLE = "<!DOCTYPE html><html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\"><title>ESP8266网页配网</title>";
String HTML_SCRIPT_ONE = "<script type=\"text/javascript\">function wifi(){var ssid = s.value;var password = p.value;var key=k.value;var xmlhttp=new XMLHttpRequest();xmlhttp.open(\"GET\",\"/HandleWifi?ssid=\"+ssid+\"&password=\"+password,true);xmlhttp.send();xmlhttp.onload = function(e){alert(this.responseText);}}</script>";
String HTML_SCRIPT_TWO = "<script>function c(l){document.getElementById('s').value=l.innerText||l.textContent;document.getElementById('p').focus();document.getElementById('k').focus();}</script>";
String HTML_CSS = "<style>html{ font-family:Helvetica;display:inline-block; margin: 0px auto; text-align: center;}body{margin-top: 50px; background-color: #4A374A; font-family: 'Open Sans',sans-serif;}#login{position: absolute;top:50%;left:50%;margin: -150px 0 0 -150px;    width: 300px;    height: 300px;   }#login h1,table,a{color: #fff;   text-shadow:0 0 10px; letter-spacing: 1px;   text-align: center; }   h1{font-size: 2em;   margin: 0.67em 0;} h3{margin: 0.67em 0;}input{width: 278px;height: 18px;margin-bottom: 10px;   outline: none;   padding: 10px;   font-size: 13px;   color: #fff;   text-shadow:1px 1px 1px;   border-top: 1px solid #312E3D;   border-left: 1px solid #312E3D; order-right: 1px solid #312E3D;   border-bottom: 1px solid #56536A;   border-radius: 4px;    background-color: #2D2D3F;   }.but{width: 300px;min-height: 40px;display: block; background-color: #4a77d4; border: 1px solid #3762bc; color: #fff;padding: 9px 14px; font-size: 15px;line-height: normal;border-radius: 5px; margin: 0;}</style>";
String HTML_HEAD_BODY_BEGIN = "</head><body><div id=\"login\"><h1>配置WIFI</h1>";
String HTML_FORM_ONE = "<form><input id='s' name='s' type=\"text\" placeholder=\"请输入您WiFi的名称\"><br><input id='p' name='p' type=\"text\" placeholder=\"请输入您WiFi的密码\"><br><input id='k' name='k' type=\"text\" placeholder=\"请输入您点灯秘钥\"><br><input class=\"but\" type=\"button\" value=\"连接\" onclick=\"wifi()\"><br><input class=\"but\" type=\"button\" value=\"扫描\" onclick=\"window.location.href = '/HandleScanWifi'\"></form>";
String HTML_BODY_HTML_END = "</div></body></html>";

wl_status_t CONNECTED = WL_CONNECTED;//重写Wifi状态函数

//重写获取WIFI状态函数，在原来基础上增加了可正常发送http请求才算WIFI状态正常
wl_status_t wifi_status(){
  wl_status_t s = WiFi.status();
  
  if(s == WL_CONNECTED){
    if(C_F){//refresh
      WiFiClient c;
      HTTPClient http;
      String urlDate = "";
      Serial.println("Test Wifi_Status");
      http.begin(c, IOTAPI_URL, 80, urlDate);
      http.setTimeout(500);
      int httpCode = http.GET(); // send the request
      http.end();
      C_F = 0;
      Serial.println(httpCode);
      if(httpCode > 0){
        CONNECTED = WL_CONNECTED;
        return WL_CONNECTED;
      }
      else{
        CONNECTED = WL_DISCONNECTED;
        return WL_DISCONNECTED;
      }
        
    }else
      return CONNECTED;
  }else{
    return s;
  }   
}



// 连接MQTT服务器
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(UID.c_str())) {
      Serial.println("connected");
      Serial.print("subscribe:");
      Serial.println(LIGHTSWIC);
      Serial.println(AIRSWIC);
      //订阅主题，如果需要订阅多个主题，可发送多条订阅指令client.subscribe(topic2);client.subscribe(topic3);
      client.subscribe(LIGHTSWIC.c_str());
      client.subscribe(AIRSWIC.c_str());
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}


// 收到信息后的回调函数
void receiveCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Topic:");
  Serial.println(topic);
  String msg = "";
  for (int i = 0; i < length; i++) {
    msg += (char)payload[i];
  }
  Serial.print("Msg:");
  Serial.println(msg);
 if(strcmp(topic,"LightSwitch002")==0){
    if(msg=="on"){
        turnJDOn();
        draw_windows(INFO, "开灯");
        delay(500);
    }
    if(msg=="off"){
        turnJDOff();
        draw_windows(INFO, "关灯");
        delay(500);
    }
  }
   if(strcmp(topic,"AIRSWITCH005")==0){
      turnAirSwitch(msg);
      draw_windows(INFO, "空调操作");
      delay(500);
   }
  msg = "";  
}


//开关遥控
void turnAirSwitch(String msg){
  String prt="";
  char charlist[10][10]={""};
  int i =0; 
  int str_len = msg.length() + 1;
  char str[str_len];
  msg.toCharArray(str,str_len);
  char *substr= strtok(str, "#");
  while(substr != NULL)
  {
      strcpy(charlist[i],substr);
      i++;
      substr = strtok(NULL,"#");
  }
  //解析开关指令
  if(strcmp(charlist[0],"on")==0){
    prt+="开空调指令--";
      _ac.on();//生成空调“开”的红外码
  }
  if(strcmp(charlist[0],"off")==0){
     prt+="关空调指令--";
      _ac.off();//生成空调“关”的红外码
  }
  //解析模式指令
  if(strcmp(charlist[1],"1")==0){
    _ac.setMode(kElectraAcAuto); prt+="自动--";
  }else if(strcmp(charlist[1],"2")==0){
    _ac.setMode(kElectraAcCool); prt+="制冷--";
  }
  else if(strcmp(charlist[1],"3")==0){
    _ac.setMode(kElectraAcHeat); prt+="制热--";
  }
  else if(strcmp(charlist[1],"4")==0){
    _ac.setMode(kElectraAcFan); prt+="送风--";
  }else if(strcmp(charlist[1],"5")==0){
    _ac.setMode(kElectraAcDry); prt+="除湿--";
  }  

  //设置温度
  String tem=charlist[2];
  if(tem!="" && tem!=NULL){
    _ac.setTemp(tem.toInt());
    prt += tem+"℃--";
  }

  //设置风速
  String fan=charlist[3];
  if(fan!="" && fan!=NULL){
    _ac.setFan(fan.toInt());
    prt += fan+"级风速--";
  }

  //设置上下或者左右扫风
   if(strcmp(charlist[4],"0")==0){
      _ac.setSwingH(false);
      prt += "关闭左右扫风--";
   }else if(strcmp(charlist[4],"1")==0){
       _ac.setSwingH(true);
      prt += "开启左右扫风--";
   }

   if(strcmp(charlist[5],"0")==0){
      _ac.setSwingV(false);
      prt += "关闭上下扫风--";
   }else if(strcmp(charlist[5],"1")==0){
       _ac.setSwingV(true);
      prt += "开启上下扫风--";
   }
  Serial.println(prt);
   prt="";
  _ac.send();//发送红外命令
}



//开关继电器
void turnJDOn(){
  Serial.println("Turn JDON");
  digitalWrite(pinJD,LOW);
}

void turnJDOff(){
  Serial.println("Turn JDOFF");
  digitalWrite(pinJD,HIGH);
}


//初始化引脚
void initPin(){
  //继电器引脚模式输出
  pinMode(pinJD, OUTPUT);
  turnJDOff();
  //空调实例初始化开始
  _ac.begin();
  dht.begin();
}

//初始化按键
void initKey(){
   button.attach(BUTTON_PIN, INPUT);
   button.interval(5);
   button.setPressedState(LOW);
}

//初始化OLED显示屏
void  initOLED(void){
  u8g2.begin();  
  u8g2.enableUTF8Print();
  u8g2.setContrast(255);
  u8g2.setFont(u8g2_font_wqy12_t_gb2312);  
}

//初始化ESP
void initBasic(void){//初始化基础
  Serial.begin(115200);
  WiFi.hostname("Smart-ESP8266");//设置ESP8266设备名
}

//设置为AP热点模式
void initSoftAP(void){//初始化AP模式
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
  if(WiFi.softAP(AP_NAME)){
    Serial.println("ESP8266 SoftAP is right");
  }
}

//初始连接WIFI
bool autoConfig(void){
  WiFi.mode(WIFI_STA);//切换为STA模式
  WiFi.setAutoConnect(true);//设置自动连接
   WiFi.begin();
  //WiFi.begin("TP-LINK_EB11","qwe1475026471");
  Serial.println("");
  Serial.print("Connect to wifi");
  
  for (int i = 0; i < 100; i++)
  {
    loading_wifi(i/1);
    if (WiFi.status() == WL_CONNECTED)
    {
      loading_wifi(i/1);
      delay(40);
      loading_wifi(100);
      delay(100);
      draw_windows(INFO, "Wif连接成功");
      Serial.println("AutoConfig Success");
      Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
      Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
      return true;
    }
    else
    {
      Serial.println("AutoConfig Waiting......");
      delay(10);
    }
  }
  return false;
}


//初始化WEB服务器
void initWebServer(void){//初始化WebServer
  server.on("/",HTTP_GET, handleRoot);
  server.onNotFound(handleRoot);//请求失败回调函数
  server.on("/HandleWifi", HandleWifi);
  server.on("/HandleScanWifi",HTTP_GET, HandleScanWifi);
  server.begin();//启动WebServer
  Serial.println("WebServer started!");
}

//强制门户认证关键
void initDNS(void){//初始化DNS服务器
  if(dnsServer.start(DNS_PORT, "*", apIP)){//判断将所有地址映射到esp8266的ip上是否成功
    Serial.println("start dnsserver success.");
  }
  else Serial.println("start dnsserver failed.");
}

//访问主页回调函数
void handleRoot() {
    Serial.println("root page");
    String str = HTML_TITLE+HTML_CSS + HTML_SCRIPT_ONE + HTML_SCRIPT_TWO + HTML_HEAD_BODY_BEGIN + HTML_FORM_ONE + HTML_BODY_HTML_END;
    server.send(200, "text/html", str);
}

//搜索检测WIFI信号强度
void HandleScanWifi() {
    Serial.println("scan start");

    String HTML_FORM_TABLE_BEGIN = "<table align=\"center\"><head><tr><th>序号</th><th>名称</th><th>强度</th></tr></head><body>";
    String HTML_FORM_TABLE_END = "</body></table>";
    String HTML_FORM_TABLE_CON = "";
    String HTML_TABLE;
    // WiFi.scanNetworks will return the number of networks found
    int n = WiFi.scanNetworks();
    Serial.println("scan done");
    if (n == 0) {
        Serial.println("no networks found");
        HTML_TABLE = "NO WIFI !!!";
    }
    else {
        Serial.print(n);
        Serial.println(" networks found");
        for (int i = 0; i < n; ++i) {
      // Print SSID and RSSI for each network found
            Serial.print(i + 1);
            Serial.print(": ");
            Serial.print(WiFi.SSID(i));
            Serial.print(" (");
            Serial.print(WiFi.RSSI(i));
            Serial.print(")");
            Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");
            delay(10);
            HTML_FORM_TABLE_CON = HTML_FORM_TABLE_CON + "<tr><td align=\"center\">" + String(i+1) + "</td><td align=\"center\">" + "<a href='#p' onclick='c(this)'>" + WiFi.SSID(i) + "</a>" + "</td><td align=\"center\">" + WiFi.RSSI(i) + "</td></tr>";
        }

        HTML_TABLE = HTML_FORM_TABLE_BEGIN + HTML_FORM_TABLE_CON + HTML_FORM_TABLE_END;
    }
    Serial.println("");

    String scanstr = HTML_TITLE+HTML_CSS + HTML_SCRIPT_ONE + HTML_SCRIPT_TWO + HTML_HEAD_BODY_BEGIN + HTML_FORM_ONE + HTML_TABLE + HTML_BODY_HTML_END;

    server.send(200, "text/html", scanstr);
}

//连接WIFI回调函数
void HandleWifi()
{
    if (server.arg("ssid")!="") {//判断是否有账号参数
    Serial.print("got ssid:");
      strcpy(my_ssid, server.arg("ssid").c_str()); //从JavaScript发送的数据中找ssid的值
      Serial.println(my_ssid);
    }
    else{
      server.send(200, "text/html", "SSID为空");
      return;
    }

    if (server.arg("password")!="") {
      Serial.print("got password:");
      strcpy(my_password, server.arg("password").c_str()); //从JavaScript发送的数据中找password的值
      Serial.println(my_password);
    }
    else{
      server.send(200, "text/html", "PassWord为空");
      return;
    }
    strcpy(my_auth, server.arg("key").c_str());
    server.send(200, "text/html", "连接中..");
    delay(2000);
}

//智能配网函数
bool smartConfig(){
  Serial.println("\r\nWait for Smartconfig配网模式");
  initSoftAP();
  initWebServer();
  initDNS();
  int counter = 0;
  while(1){
    u8g2.firstPage();
    do{
      u8g2.drawXBMP(0,0, 64, 64, wifi);
      u8g2.setCursor(65,34);
      u8g2.print("等待配网");
      u8g2.drawXBMP(75, 50, 8, 8, counter % 3 == 0 ? activeSymbole : inactiveSymbole);
      u8g2.drawXBMP(85, 50, 8, 8, counter % 3 == 1 ? activeSymbole : inactiveSymbole);
      u8g2.drawXBMP(95, 50, 8, 8, counter % 3 == 2 ? activeSymbole : inactiveSymbole);
    }while(u8g2.nextPage()); 
    delay(500);
    counter++;
     server.handleClient();
    dnsServer.processNextRequest();
    int flag = 1;
    if(server.arg("ssid")!="" and server.arg("password")!=""){
      WiFi.mode(WIFI_STA);//切换为STA模式
      WiFi.setAutoConnect(true);//设置自动连接
      WiFi.begin(my_ssid,my_password);
      while(flag){
      switch(WiFi.status()){
        case WL_IDLE_STATUS: draw_windows(INFO,"正在连接...");break;//正在连接
        case WL_CONNECTED: server.stop();draw_windows(INFO,"Wifi连接成功");flag = 0;break;//连接
        case WL_CONNECT_FAILED: 
          draw_windows(ERR,"密码错误");
          delay(2000);
          draw_windows(INFO,"请重试");
          delay(2000);
          flag = 0;
          break;//连接失败
        case WL_DISCONNECTED: draw_windows(INFO,"等待连接..");break;
        default: break;
      }
      delay(100);
     
    }
  }
  if(WiFi.status() == WL_CONNECTED){//如果连接上 就输出IP信息
      Serial.println("WIFI Connected!");
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());//打印esp8266的IP地址
      break;
    }
  }
  return true;
}


//系统启动时调用的WIFI开启
bool wifi_Start(){
  if(!autoConfig()){
    return smartConfig();
  }  
  return true;
}

//绘制配网wifi页面
int count=0;
void loading_wifi(int i){
  if(count>44){
    count=0;
  }
  u8g2.firstPage();
  do{
    u8g2.drawXBMP(17,0, 94, 64, IMG[count]);
    u8g2.drawBox(0,62,(int)i*1.28,2);
  }while(u8g2.nextPage());
  count++;
}

//绘制提示窗口页面
void draw_windows(int type, String s ){
  u8g2.firstPage();
  do{
    Serial.println(s);
  int len = sizeof(s);
  if(len < 42){
    u8g2.drawLine(8, 13, 119, 13);
    u8g2.drawLine(8, 55, 119, 55);
    u8g2.drawFilledEllipse(14, 6, 2, 2, U8G2_DRAW_ALL);
    u8g2.drawFilledEllipse(22, 6, 2, 2, U8G2_DRAW_ALL);
    u8g2.drawFilledEllipse(30, 6, 2, 2, U8G2_DRAW_ALL);
    u8g2.drawRFrame(8,0,112,64,4);
    u8g2.setFont(u8g2_font_6x10_mf);
    if(type == 1){
      u8g2.drawStr(45, 10, "WARNING!");
      u8g2.setFont(u8g2_font_open_iconic_check_2x_t);
      u8g2.drawGlyph(14, 43, 71);//WARNING iconic
    }  
    else if(type == 2){
      u8g2.drawStr(50, 10, "INFO");
      u8g2.setFont(u8g2_font_open_iconic_check_2x_t);
      u8g2.drawGlyph(14, 43, 65);//info iconic
    }
    else if(type == 0){
      u8g2.drawStr(50, 10, "ERROR!!!");
      u8g2.setFont(u8g2_font_open_iconic_check_2x_t);
      u8g2.drawGlyph(14, 43, 66);//error iconic
    }

  }else{
    u8g2.drawRFrame(0,0,127,63,4);
    u8g2.drawRFrame(2,2,123,58,3);
  }
  u8g2.setFont(u8g2_font_wqy12_t_gb2312);
  u8g2.setCursor(35, 39);
  u8g2.print(s);
  }while(u8g2.nextPage()); 
}



//时间配置更新
void ntp_setup(){
  TIME_CLIENT.begin();
  TIME_CLIENT.update();
  while (!TIME_CLIENT.updated()){
    Serial.println("******NOT UPDATED******");
    delay(50);
    Serial.println("******UPDATED TIME******");
    TIME_CLIENT.update();
  }  
}

//取地址
int get_location(){
  if(wifi_status() == WL_CONNECTED){
    Serial.println("start get location from ip ");
    WiFiClient c;
    char str[]="";
    char charlist[10][10]={""};
    int i =0; 
    HTTPClient http; //Declare an object of class HTTPClient
    
    String urlDate = "/api/device/v1/data/1/get/?uid="+UID+"&topic=" + IPS;
    http.begin(c, IPSTACKAPI_URL, 80, urlDate);
    http.setTimeout(500);
    int httpCode = http.GET(); // send the request
    
    if (httpCode > 0) // check the returning code
    {
      Serial.println("httpcode ok");
      String input = http.getString(); //Get the request response input
      http.end();
      Serial.println("地址输出"+input);
      // Stream& input;

      StaticJsonDocument<200> doc;

      DeserializationError error = deserializeJson(doc, input);

      if (error) {
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.f_str());
        return 0;
      }
      strcpy(str, doc["msg"]); // "郑州"
      char *substr= strtok(str, "#");
      while(substr != NULL)
      {
        strcpy(charlist[i],substr);
        i++;
        substr = strtok(NULL,"#");
      }
      strcpy(city_CH, charlist[0]);
      strcpy(city, charlist[1]);
      Serial.println(city_CH);
      Serial.println(city);
      return 1;
    }else{
      http.end();
      Serial.println("httpcode bad");
      return 0;
    }
  }
  else return 0;
}

//取温湿度值
bool get_DHT11(){
//  int err = SimpleDHTErrSuccess;
//  if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
//    Serial.println("Read DHT11 failed, err="); Serial.println(err);
//    return false;
//  }
//  else{
//    return true;
//  }
    humidity=dht.readHumidity();
    temperature=dht.readTemperature();
    if(temperature<=100){
      Serial.print("Temperature:");                      
      Serial.println(temperature);    
    }else{
       Serial.print("未读取到温度数据"); 
       temperature=0;
    }
                                 
    if(humidity<=100){
      Serial.print("Humidity:");                            
       Serial.print(humidity);                                    
        Serial.println("%");  
    }else{
      Serial.print("未读取到湿度数据");
      humidity=0;
    }
                                  
}

//绘制WIFI连接状态图标
void draw_State(){
    u8g2.setFont(u8g2_font_open_iconic_www_1x_t);
    if(wifi_status()== WL_CONNECTED){
        u8g2.drawGlyph(0, 10, 72);
    }else if(wifi_status() == WL_DISCONNECTED ){
        if((TIME_CLIENT.getEpochMillis()%1000) > 500)
          u8g2.drawGlyph(0, 10, 69); 
    }else if(wifi_status() == WL_NO_SSID_AVAIL ){
        if((TIME_CLIENT.getEpochMillis()%1000) > 500)
          u8g2.drawGlyph(0, 10, 79); 
    }else if(wifi_status() == WL_IDLE_STATUS ){
        if((TIME_CLIENT.getEpochMillis()%1000) > 500)
          u8g2.drawGlyph(0, 10, 81); 
    }

    //show weather state

}

//绘制时钟界面
void draw_clock(){
   
    HOURS = TIME_CLIENT.getHours();
    MINS =  TIME_CLIENT.getMinutes();
    SECS =  TIME_CLIENT.getSeconds();

    
    u8g2.setFont(u8g2_font_logisoso30_tn);
    u8g2.drawStr(0,46,TIME_CLIENT.getStrHours().c_str());
    u8g2.drawStr(45,46,TIME_CLIENT.getStrMinutes().c_str());
    u8g2.drawStr(88,46,TIME_CLIENT.getStrSeconds().c_str());

    if((TIME_CLIENT.getEpochMillis()%1000) < 333){
      u8g2.drawStr(36,46,":");
      u8g2.drawStr(80,46," ");
    }else if((TIME_CLIENT.getEpochMillis()%1000) < 666){
      u8g2.drawStr(36,46," ");
      u8g2.drawStr(80,46,":");
    }
    else {
      u8g2.drawStr(80,46," ");
      u8g2.drawStr(80,46," ");
    }
      
}

//绘制温湿度界面
void draw_Sensor(){
  u8g2.setFont(u8g2_font_wqy12_t_gb2312);
  //u8g2.setFont(u8g2_font_6x10_mf);
  u8g2.setCursor(16,12);
  u8g2.print("当前温湿度气体值");
  u8g2.setCursor(3,26);
  u8g2.print("温度");
  u8g2.drawRFrame(28,18,75,8,2);
  u8g2.drawBox(28, 18, temperature/1.5, 8);
  u8g2.setCursor(105, 26);
  u8g2.print(temperature);

  u8g2.setCursor(3,26+12);
  u8g2.print("湿度");
  u8g2.drawRFrame(28,18+12,75,8,2);
  u8g2.drawBox(28, 18+12, humidity/1.5, 8);
  u8g2.setCursor(105, 26+12);
  u8g2.print(humidity);

//  u8g2.setCursor(3,26+24);
//  u8g2.print("气体");
//  u8g2.drawRFrame(28,18+24,75,8,2);
//  u8g2.drawBox(28, 18+24, sensorValue/20, 8);
//  u8g2.setCursor(105, 28+22);
//  u8g2.print(sensorValue);

//  u8g2.drawStr(3, 22+36, "90");
//  u8g2.drawRFrame(28,18+36,90,8,2);
//  u8g2.drawBox(28, 18+36, PROBABILITY[3]*90, 8);
}

//绘制底部页面
void draw_foot(bool location){
  u8g2.setFont(u8g2_font_6x10_mf);
  if(location){
    u8g2.drawStr(2,62,(String(TIME_CLIENT.getMonth()) + "/" + TIME_CLIENT.getDay() ).c_str());
    u8g2.drawStr(30,62,TIME_CLIENT.getDoW().c_str());
    u8g2.setFont(u8g2_font_wqy12_t_gb2312);
    u8g2.setCursor(66, 62);
    u8g2.print(city_CH);
    u8g2.setFont(u8g2_font_open_iconic_www_1x_t);
    u8g2.drawGlyph(56, 63, 64); 
  }else{
    u8g2.drawStr(12,64,(String(TIME_CLIENT.getMonth()) + "/" + TIME_CLIENT.getDay() ).c_str());
    u8g2.drawStr(90,64,TIME_CLIENT.getDoW().c_str());
  }
  
}

//绘制滚动字幕效果
void drawScrollString(int x_offset,int16_t offset, const char *s){
  static char buf[36];  // should for screen with up to 256 pixel width 
  size_t len;
  size_t char_offset = 0;
  u8g2_uint_t dx = 0;
  size_t visible = 0;
  len = strlen(s);
  if ( offset < 0 )
  {
    char_offset = (-offset)/1;
    dx = offset + char_offset*1;
    if ( char_offset >= u8g2.getDisplayWidth()/1 )
      return;
    visible = u8g2.getDisplayWidth()/1-char_offset+1;
    strncpy(buf, s, visible);
    buf[visible] = '\0';
    u8g2.setFont(u8g2_font_wqy12_t_gb2312);
    u8g2.setCursor(char_offset*1 - dx + x_offset,10);
    u8g2.print(buf);
  }
  else
  {
    char_offset = offset / 1;
    if ( char_offset >= len )
      return; // nothing visible
    dx = offset - char_offset*1;
    visible = len - char_offset;
    if ( visible > u8g2.getDisplayWidth()/1+1 )
      visible = u8g2.getDisplayWidth()/1+1;
    strncpy(buf, s+char_offset, visible);
    buf[visible] = '\0';
    u8g2.setFont(u8g2_font_wqy12_t_gb2312);
    u8g2.setCursor(-dx + x_offset,10);
    u8g2.print(buf);
  }
  
}

//绘制滚动字幕
void draw_state_scroll(){
    drawScrollString(16,OFFSET, MSG);
    int16_t len = strlen(MSG);
    OFFSET+=2;
    if ( OFFSET > len*8+1 ){
      C_F = 1;
      get_slogan();
      OFFSET = -(int16_t)u8g2.getDisplayWidth();
    }
}

//取云平台存放的滚动字幕数据
int get_slogan(){
//  if(wifi_status() == WL_CONNECTED){
//    WiFiClient c;
//    HTTPClient http; //Declare an object of class HTTPClient
//    
//    String urlDate = "/api/device/v1/data/1/get/?uid="+UID+"&topic="+USR;
//
//    Serial.println("start refresh ");
//    http.begin(c, IOTAPI_URL,80,urlDate);
//    http.setTimeout(500);
//    int httpCode = http.GET(); // send the request
//    
//    if (httpCode > 0) // check the returning code
//    {
//      Serial.println("httpcode ok");
//      String input = http.getString(); //Get the request response input
//      http.end();
//      Serial.println("信息输出"+input);
//      StaticJsonDocument<200> doc;
//      DeserializationError error = deserializeJson(doc, input);
//      if (error) {
//        Serial.print(F("deserializeJson() failed: "));
//        Serial.println(error.f_str());
//        
//        return 0;
//      }
//      LAST_TIME = TIME;
//      TIME = doc["time"]; // 1614248446
//      strcpy(MSG, doc["msg"]); // "There is only one heroism in the world: to see the world as it is and ...
//      if(LAST_TIME == TIME)
//          return 0;
//      else
//          return 1;
//    }else{
//      http.end();
//      Serial.println("httpcode bad");
//      return 0;
//    }
//  }else return 0;
    return 0;
}

//绘制整体OLED系统界面函数
void frame(){
  u8g2.firstPage();
  do{
      if(PAGE==0){
        draw_state_scroll();
        draw_State();
        draw_clock();
        draw_foot(true);  
      }
      if(PAGE==1){
        draw_Sensor();  
      }
  }while(u8g2.nextPage());
}

//定义按键功能
void Key(){
  button.update();
  if (button.pressed()){
    PAGE++;
    Serial.println("按键被触发");
    if(PAGE%2==0){
      PAGE=0;  
    }
    else{
      PAGE=1;  
    }
  }
}


void doMqttClick(){
   if (!client.connected()) {
      reconnect();
    }else{
      client.loop();    // 保持心跳
    } 
}

//计数
void tickerCount(){
  tickercount++;
}

//上传数据
void pubMQTTmsg(){
  if(wifi_status() == WL_CONNECTED){
      char publishTopic[dht11TopicString.length() + 1];  //转换成字符数组
      strcpy(publishTopic, dht11TopicString.c_str());
      String data="#"+String(temperature)+"#"+String(humidity);
      Serial.println(data);
       char publishMsg[data.length() + 1];
        strcpy(publishMsg, data.c_str());
      // 实现ESP8266向主题发布信息,并在串口监视器显示出来
        if(client.publish(publishTopic, publishMsg)){
            Serial.println("Publish Topic:");
            Serial.println(publishTopic);
            Serial.println("Publish message:");
            Serial.println(publishMsg);    
        } else {
      Serial.println("Message Publish Failed."); 
    }
  }
}


//定时获取传感器数据并上传
void getSensorAndUpdate(){
  if (tickercount >= 5){ // 每隔5秒钟发布一次信息
        get_DHT11();
        pubMQTTmsg();
        tickercount = 0;
  }  
}

void setup() {
  // put your setup code here, to run once:
  //初始化需要用到的引脚
  initPin();
  //初始化OLED屏幕
  initOLED();
  //初始化esp
  initBasic();
  //调用wifi连接方法
  wifi_Start();
  Serial.println("Start Init...");
  Serial.println("ntp Init...");
  //如果连接上了，初始化时间
  if(WiFi.status() == WL_CONNECTED){
    client.setServer(mqtt_server, 9501);//设置mqtt服务器
    client.setCallback(receiveCallback); //mqtt消息处理 
    ntp_setup();
    get_location();
    initKey();
    ticker.attach(1, tickerCount); // Ticker定时对象
  }
}

void loop() {
  // put your main code here, to run repeatedly:
   if (millis() - T > TPF) {
    T = millis();
    frame();
    //doTCPClientTick();
    doMqttClick();
    Key();
    getSensorAndUpdate();
   }
}
